package nuonuo.com.view.customview;

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Scroller;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

import nuonuo.com.view.R;

/**
 * Created by n6 on 2017/3/10.
 */

public class CustomPtr extends ViewGroup {
    private static final int MODE_NONE = 0;
    private static final int MODE_PULL_TO_REFRESH = 1;
    private static final int MODE_RELEASE_FRESH = 2;
    private static final int MODE_FRESHING = 3;
    private static final int MODE_FINISH_REFRESH = 4;
    private Scroller mScroller;
    private View headView;

    private int state = MODE_NONE;
    private boolean intercept;
    private int eventX;
    private int eventY;
    private int eventAction;
    private int touchX;
    private int touchY;
    private int touchAction;
    private TextView tvPtr;
    private ImageView ivPtr;
    private ObjectAnimator animator;

    public CustomPtr(Context context) {
        this(context,null);
    }

    public CustomPtr(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }
    public CustomPtr(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        Logger.i(1+"");
        init();
    }

    private void init() {
        mScroller = new Scroller(getContext());
        headView = LayoutInflater.from(getContext()).inflate(R.layout.ptr_refresh_view,this,false);
        addView(headView);
    }

    private int mLastX,mLastY;
    private int mInterceptX,mInterceptY;
    private boolean hasIntercept;

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (mHeadViewHeight == 0){
            mHeadViewHeight = headView.getHeight();
            ivPtr = (ImageView) headView.findViewById(R.id.iv_icon);
            tvPtr = (TextView) headView.findViewById(R.id.tv_content);
        }
        eventAction = ev.getAction();
        eventX = (int) ev.getX();
        eventY = (int) getY();
        intercept = false;
        switch (eventAction){
            case MotionEvent.ACTION_DOWN:
                intercept = false;
                hasIntercept = false;
                if (!mScroller.isFinished()){
                    mScroller.abortAnimation();
                    intercept = true;
                    hasIntercept = true;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                Logger.i((eventY - mInterceptY)+"");
                if (state != MODE_NONE){
                    intercept = true;
                    hasIntercept = true;
                    break;
                }
                if (getScrollY() == 0){
                    if (eventY > mInterceptY){
                        intercept = true;
                        hasIntercept = true;
                    }else {
                        hasIntercept = false;
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                break;
            default:
                break;
        }
        mInterceptX = eventX;
        mInterceptY = eventY;
        return false;
    }

    private int mHeadViewHeight;
    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        touchAction = event.getAction();
        touchX = (int) event.getX();
        touchY = (int) event.getY();
        switch(touchAction) {
            case MotionEvent.ACTION_DOWN:
                if (!mScroller.isFinished()){
                    mScroller.abortAnimation();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (touchY > mLastY || state != MODE_NONE){
                    scrollBy(0,mLastY - touchY);
                    if (Math.abs(getScrollY()) >= mHeadViewHeight){
                        if (state == MODE_PULL_TO_REFRESH){
                            releaseToRefresh();
                        }else {
                            state = MODE_RELEASE_FRESH;
                        }
                    }else {
                        if (state == MODE_RELEASE_FRESH){
                            pullToRefresh();
                        }else {
                            state = MODE_PULL_TO_REFRESH;
                        }
                    }
                }else {
                    smoothScrollTo(0,0);
                }
                break;
            case MotionEvent.ACTION_UP:
                if (state == MODE_PULL_TO_REFRESH){
                    smoothScrollTo(0,0);
                    state = MODE_NONE;
                }else if (state == MODE_RELEASE_FRESH){
                    smoothScrollTo(0,-mHeadViewHeight);
                    refresh();
                }
                break;
            default:
                break;
        }
        mLastX = touchX;
        mLastY = touchY;
        return true;
    }

    private void releaseToRefresh() {
        ObjectAnimator.ofFloat(ivPtr,"rotationX",0,180).setDuration(500).start();
        tvPtr.setText("释放刷新");
        state = MODE_RELEASE_FRESH;
    }

    private void pullToRefresh(){
        ObjectAnimator.ofFloat(ivPtr,"rotationX",180,0).setDuration(500).start();
        tvPtr.setText("下拉刷新");
        state = MODE_PULL_TO_REFRESH;
    }

    private void refresh() {
        state = MODE_FRESHING;
        ivPtr.setImageResource(R.mipmap.spinner_16_inner_holo);
        tvPtr.setText("正在刷新");
        animator = ObjectAnimator.ofFloat(ivPtr, "rotation", 0, -360);
        animator.setDuration(1000).setRepeatCount(ValueAnimator.INFINITE);
        animator.start();
        postDelayed(new Runnable() {
            @Override
            public void run() {
                finishRefresh();
            }
        },2000);
    }

    public void finishRefresh(){
        state = MODE_NONE;
        animator.end();
        tvPtr.setText("下拉刷新");
        ivPtr.setImageResource(R.mipmap.pulltorefresh_down_arrow);
        ObjectAnimator.ofFloat(ivPtr,"rotationX",180,0).setDuration(500).start();
        Toast.makeText(getContext(), "刷新完成", Toast.LENGTH_SHORT).show();
        smoothScrollTo(0,0);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        List<View> list = new ArrayList<>();
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        int height = 0;
        int childCount = getChildCount();
        switch (heightMode) {
            case MeasureSpec.UNSPECIFIED:
                heightMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
                measureChildren(widthMeasureSpec, heightMeasureSpec);
            case MeasureSpec.AT_MOST:
                for (int i = 0; i < childCount; i++) {
                    View child = getChildAt(i);
                    MyHorizantalScrollerView.LayoutParams params = (MyHorizantalScrollerView.LayoutParams) child.getLayoutParams();
                    if (params.height == ViewGroup.LayoutParams.MATCH_PARENT) {
                        list.add(child);
                    } else if (params.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
                        height = Math.max(height, child.getMeasuredHeight() + params.bottomMargin + params.topMargin);
                    } else if (params.height > 0) {
                        height = Math.max(height, child.getMeasuredHeight() + params.bottomMargin + params.topMargin);
                    }
                }
                if (list.size() != 0) {
                    int realHeightSpec;
                    for (int i = 0; i < list.size(); i++) {
                        View child = list.get(i);
                        MyHorizantalScrollerView.LayoutParams params = (MyHorizantalScrollerView.LayoutParams) child.getLayoutParams();
                        if (child.getMeasuredHeight() < (height - params.bottomMargin - params.topMargin)) {
                            realHeightSpec = MeasureSpec.makeMeasureSpec(height - params.bottomMargin - params.topMargin, MeasureSpec.EXACTLY);
                            measureChild(child, widthMeasureSpec, realHeightSpec);
                        }
                    }
                }
                break;
            case MeasureSpec.EXACTLY:
                MarginLayoutParams params = (MarginLayoutParams) getLayoutParams();
                height = getMeasuredHeight() + params.topMargin + params.bottomMargin;
                break;
        }
        setMeasuredDimension(getMeasuredWidth(), height);
    }

    public static class LayoutParams extends MarginLayoutParams{

        public LayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);
        }

        public LayoutParams(int width, int height) {
            super(width, height);
        }

        public LayoutParams(MarginLayoutParams source) {
            super(source);
        }

        public LayoutParams(ViewGroup.LayoutParams source) {
            super(source);
        }
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LayoutParams(getContext(), attrs);
    }

    @Override
    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
        if (lp instanceof LayoutParams) {
            return new LayoutParams((LayoutParams) lp);
        } else if (lp instanceof MarginLayoutParams) {
            return new LayoutParams((MarginLayoutParams) lp);
        } else {
            return new LayoutParams(lp);
        }
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()){
            scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
            postInvalidate();
        }
    }

    private void smoothScrollTo(int destX,int destY){
        int scrollY = getScrollY();
        int deltaY = destY - scrollY;
        mScroller.startScroll(0,scrollY,0,deltaY,500);
        invalidate();
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childCount = getChildCount();
        int currentHeight = 0;
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();
            LayoutParams params = (LayoutParams) child.getLayoutParams();
            if (i == 0){
                child.layout(params.leftMargin, -(params.topMargin + childHeight + params.bottomMargin), params.leftMargin + childWidth, -params.bottomMargin);
                Logger.i(child.getTop()+"");
            }else {
                child.layout(params.leftMargin, params.topMargin + currentHeight, params.leftMargin + childWidth, params.topMargin + childHeight + currentHeight);
                currentHeight += (params.topMargin + childHeight + params.bottomMargin);
            }
        }
    }
}
